<?
// Added this for fun.
class Wiki_model extends Model {

	function __construct() {
		parent::Model();
	}

	function get_system_wiki($requested_wiki) {
		$special_wiki_type = $requested_wiki[0];
		$special_wiki_name = $requested_wiki[1];
		$wiki['username'] = "System";
		$wiki['created_on'] = "Then";
		
		switch($special_wiki_type) {
		case 'tag':
			$tag = $special_wiki_name;
			$wiki['content'] = $this->expand_system_wiki($this->get_wiki_words_by_tag($tag));
			if ($tag == "WikiStyle") {
				$wiki['wiki_style'] = true;
			}
			break;
		case 'created':
			$author = $special_wiki_name;
			$wiki['content'] = $this->expand_system_wiki($this->get_wiki_words_created_by($author));
			break;
		case 'touched':
			$author = $special_wiki_name;
			$wiki['content'] = $this->expand_system_wiki($this->get_wiki_words_touched_by($author));
			break;
		case 'lastedit':
			$author = $special_wiki_name;
			$wiki['content'] = $this->expand_system_wiki($this->get_wiki_words_last_edited_by($author));
			break;
		case 'system':
			if ($special_wiki_name == 'all') {
				$wiki['content'] = $this->expand_system_wiki($this->get_all_wiki_words());
				break;
			}
		default:
			$wiki['content'] = "*This SystemWiki cannot be created.*";
		}
		
		return $wiki;
	}

	function get_all_wiki_words() {
		$this->db->select('wiki_word, clicks')->from('wiki_group');
		$this->db->orderby("wiki_word","asc"); 
		$query = $this->db->get();
		return $query->result_array();
	}

	function get_wiki_words_last_edited_by($author) {
		$this->db->select('wiki_word, clicks')->from('wiki_group');
		$this->db->join('author', 'wiki_group.last_edit_id = author.author_id');
		$this->db->where('author.username',$author);
		$this->db->orderby('wiki_word');
		$query = $this->db->get();
		return $query->result_array();

	}

	function get_wiki_words_created_by($author) {

		$this->db->select('wiki_word, clicks')->from('wiki_group');
		$this->db->join('author', 'wiki_group.author_id = author.author_id');
		$this->db->where('author.username',$author);
		$this->db->orderby('wiki_word');
		$query = $this->db->get();
		return $query->result_array();

	}

	function get_wiki_words_touched_by($author) {
		$this->db->select('DISTINCT wiki_group.wiki_word, clicks')->from('wiki');
		$this->db->join('author','wiki.author_id = author.author_id');
		$this->db->join('wiki2group', 'wiki.wiki_id = wiki2group.wiki_id');
		$this->db->join('wiki_group', 'wiki_group.wiki_group_id = wiki2group.wiki_group_id');
		$this->db->where('username',$author);
		$query = $this->db->get();
		return $query->result_array();
	}

	function get_wiki_by_wiki_word($wiki_word) {
		if ($this->check_valid_wiki_word($wiki_word)) {
			$select_columns = array('username', 'content', 'wiki.created_on');
			$wiki = $this->get_wikis_by_wiki_word($wiki_word, $select_columns, 1);
			if (count($wiki) > 0) {
				return $wiki[0];
			} else {
				$wiki['content'] = "*'$wiki_word' does not yet exist. Double click to edit.*";
			        $wiki['username'] = "You";
				$wiki['created_on'] = "Now";
				return $wiki;
			}
		} else {
			$wiki['content'] = "*'$wiki_word' is not a valid WikiWord.  Thank you, come again.*";
			$wiki['username'] = "You";
			$wiki['created_on'] = "Now";
			return $wiki;
		}
	}

	function get_wikis_by_wiki_word($wiki_word, $select_columns, $limit = null) {
		$this->db->select($select_columns)->from('wiki');
		$this->db->join('author','wiki.author_id = author.author_id');
		$this->db->join('wiki2group', 'wiki.wiki_id = wiki2group.wiki_id');
		$this->db->join('wiki_group', 'wiki_group.wiki_group_id = wiki2group.wiki_group_id');
		$this->db->where('wiki_group.wiki_word',$wiki_word);
		$this->db->orderby("wiki.created_on", "desc"); 
		if (!is_null($limit)) {
			$this->db->limit($limit);
		}
		$query = $this->db->get();
		return $query->result_array();
	}

	function get_tags_by_wiki_word($wiki_word) {
		$this->db->select('tag')->from('tag');
		$this->db->join('tags2wiki_group','tags2wiki_group.tag_id = tag.tag_id');
		$this->db->join('wiki_group','tags2wiki_group.wiki_group_id = wiki_group.wiki_group_id');
		$this->db->where('wiki_group.wiki_word',$wiki_word);
		$query = $this->db->get();
		return $query->result_array();

	}

	function get_wiki_group_id($wiki_word) {

		$this->db->select('wiki_group_id')->from('wiki_group')->where('wiki_word',$wiki_word);
		$query = $this->db->get();
		if ($query->num_rows() > 0) {
			$row = $query->row();
			return $row->wiki_group_id;
		} else {
			return false;
		}
	}

	function claim_last_edit($wiki_word,$author) {
		$this->db->where('wiki_word',$wiki_word);
		$this->db->update('wiki_group', array('last_edit_id' => $author['author_id']));
	}

	function create_wiki_group($wiki_word,$author) {
		if ($wiki_group_id = $this->get_wiki_group_id($wiki_word)) {
			$this->claim_last_edit($wiki_word,$author);
			return $wiki_group_id;
		} else {
			$this->db->insert('wiki_group', array('wiki_word' => $wiki_word, 'author_id' => $author['author_id'], 'last_edit_id' => $author['author_id']));
			return $this->db->insert_id();
		}
	}

	function create_wiki($wiki_group_id, $author, $content = null) {

		if (is_null($content)) {
			$wiki['content'] = $this->input->post('value');
		} else {
			$wiki['content'] = $content;
		}

		#checking to see duplicates and if so, ignoring the create
		$this->db->select('content, wiki.author_id, wiki.created_on, author.username as author')->from('wiki');
		$this->db->join('wiki2group', 'wiki.wiki_id = wiki2group.wiki_id');
		$this->db->join('wiki_group', 'wiki_group.wiki_group_id = wiki2group.wiki_group_id');
		$this->db->join('author', 'wiki.author_id = author.author_id');
		$this->db->where('wiki_group.wiki_group_id',$wiki_group_id);
		$this->db->orderby("wiki.created_on", "desc"); 
		$this->db->limit(1);
		$query = $this->db->get();
		if ($query->num_rows() > 0) {
			$row = $query->row_array();
			if ($wiki['content'] == $row['content']) {
				return $row;
			} 
		}
		$wiki['author_id'] = $author['author_id'];
		$wiki['created_on'] = date('Y-m-d H:i:s');
		$this->db->insert('wiki',$wiki);
		$wiki_id = $this->db->insert_id();

		$wiki['author'] = $author['username'];
		$wiki2group['wiki_group_id'] = $wiki_group_id;
		$wiki2group['wiki_id'] = $wiki_id;
		$this->db->insert('wiki2group',$wiki2group);

		return $wiki;

	}


	function xhtmlify_wiki_data($wiki) {
		$this->load->helper('markdown');
		$wiki['content'] = markdown($wiki['content']);
		return $wiki;
	}

	function empty_wiki_word($wiki_word) {
		$wikis = $this->get_wikis_by_wiki_word($wiki_word,'wiki.wiki_id',1);
		if (count($wikis) > 0) {
			return false;
		} else {
			return true;
		}
	}

	private function get_wiki_regexp() {
		return '/(?!<.*?)([a-z0-9]*[A-Z]+[a-z0-9]+[A-Z]+[A-Za-z0-9]*)(?![^<>]*?>)/';
	}
		
	function create_wiki_links($wiki) {
		#$capital_regexp = '/[a-z0-9]*[A-Z][a-z0-9]+[A-Z][A-Za-z0-9]*/';
		$matches = array();
		$capital_regexp = $this->get_wiki_regexp();
		preg_match_all($capital_regexp,$wiki['content'],$matches, PREG_PATTERN_ORDER);
		$num = count($matches[0]);
		if ($num > 0) {
			$anon_function = '$word_class = array(';
			$i=0;
			foreach ($matches[0] as $match) {
				if ($this->empty_wiki_word($match)) {
					$anon_function .= '"'.$match.'" => "not_created"';
				} else {
					$anon_function .= '"'.$match.'" => "wiki_word"';
				}
				if ($i!=$num) {
					$anon_function .= ',';
				}
				$i++;
			}
			$anon_function .= '); return anchor("wiki/view/".$matches[0], $matches[0], array("class" => $word_class[$matches[0]]));';
			$wiki_anchor = create_function('$matches', $anon_function);
			$this->load->helper('url');
			$wiki['content'] = preg_replace_callback($capital_regexp,$wiki_anchor,$wiki['content']);
		}
		return $wiki;
	}

	function expand_system_wiki($wiki_array) {
		$total = count($wiki_array);
		$classes = array('smallestTag', 'smallTag', 'mediumTag','mediumerTag', 'largeTag', 'largestTag');
		$tag_count = count($classes) - 1;
		#cheap!
		$min = 99999999999999;
		$max = 0;
		foreach ($wiki_array as $w) {
			if ($w['clicks'] > $max) {
				$max = $w['clicks'];
			} elseif ($w['clicks'] < $min) {
				$min = $w['clicks'];
			}
		}
		$step = ($max-$min) / $tag_count;
		if (is_array($wiki_array)) {
			$expanded_wiki = "";
			foreach ($wiki_array as $w ) {
				if ($min != $max) {
					$index = floor($w['clicks'] / $step);
				} else {
					$index = 0;
				}
				$expanded_wiki .= "<li class=\"".$classes[$index]."\">".$w['wiki_word']."</li>\n";
			}
			$wiki_array = '<ul class="tag_cloud">'.$expanded_wiki."</ul>";
		}
		return $wiki_array;
	}

	function prepare_wiki($wiki) {
		$wiki = $this->xhtmlify_wiki_data($wiki);
		$wiki = $this->create_wiki_links($wiki);
		return $wiki;
	}

	function add_bread_crumbs($wiki_word,$author,$max) {

		$clicked_time = date('Y-m-d H:i:s');
		if ($wiki_group_id = $this->get_wiki_group_id($wiki_word)) {
			$sql = "REPLACE INTO bread_crumbs SET author_id = ?, wiki_group_id = ?, clicked_time = '".$clicked_time."'";
			$this->db->query($sql, array($author['author_id'], $wiki_group_id));
		}

		$this->db->select('wiki_group.wiki_word, bread_crumbs.clicked_time')->from('wiki_group');
		$this->db->join('bread_crumbs','bread_crumbs.wiki_group_id = wiki_group.wiki_group_id');
		$this->db->where('bread_crumbs.author_id',$author['author_id']);
		$this->db->orderBy('bread_crumbs.clicked_time', 'desc');
		$this->db->limit($max);

		$query = $this->db->get();

		foreach($query->result_array() as $row) {
			$results[] = $row['wiki_word'];
		}
		$oldest = $row['clicked_time'];

		if (count($results) == $max) {
			$this->db->where('clicked_time <', $oldest);
			$this->db->delete('bread_crumbs');
		}

		return $results;
	}

	function get_condensed_wiki_history($wiki_word) {

		$select_columns = array('wiki.wiki_id', 'wiki.content', 'author.username as author', 'wiki.created_on');
		$wikis = $this->get_wikis_by_wiki_word($wiki_word,$select_columns);
		$reference_wiki = $wikis[0];
		$result_wikis = array();
		$percentage = 0.0;
		foreach ($wikis as $wiki) {
			similar_text($reference_wiki['content'],$wiki['content'],&$percentage);
			$wiki['similarity'] = number_format($percentage,2)."%";
			unset($wiki['content']);
			$result_wikis[] = $wiki;
		}

		return $result_wikis;
	}

	function get_wiki_words_by_tag($tag) {
	
		$this->db->select('wiki_group.wiki_word, clicks')->from('wiki_group');
		$this->db->join('tags2wiki_group', 'wiki_group.wiki_group_id = tags2wiki_group.wiki_group_id');
		$this->db->join('tag', 'tag.tag_id = tags2wiki_group.tag_id');
		$this->db->where('tag.tag',$tag);
		$query = $this->db->get();
		return $query->result_array();
	}

	function create_tags($wiki_word) {

		if (!$wiki_group_id = $this->get_wiki_group_id($wiki_word)) {
			return false;
		}
		if (!$tags = $this->input->post('value', TRUE)) {
			return false;
		}
		$old_tags = array();
		$this->db->select('tag.tag_id')->from('tags2wiki_group')->where('wiki_group_id',$wiki_group_id);
		$query = $this->db->get('tag');
		foreach($query->result_array() as $row) {
			$old_tags[$row['tag_id']] = $row['tag_id'];
		}

		//Delete the old tag bindings, add the tags if necessary, and then assign them to that wiki_group
		$tags_raw = split(',', $tags);
		foreach ($tags_raw as $raw) {
			$tag_list[] = trim($raw);
		}

		$this->db->where('wiki_group_id', $wiki_group_id);
		$this->db->delete('tags2wiki_group');
		foreach ($tag_list as $tag) {
			$this->db->orwhere(array('tag' => $tag));
		}
		$query = $this->db->get('tag');
		$existing_tag = array();
		foreach ($query->result_array() as $row) {
			$existing_tag[$row['tag']] = $row['tag_id'];
		}

		if (count($existing_tag) < count($tag_list)) {
			$insert_tag = array();
			foreach ($tag_list as $tag) {
				if (!array_key_exists($tag,$existing_tag)) {
					$insert_tag[] = array('tag' => $tag);
				}
			}
			foreach ($insert_tag as $tag) { 
				$this->db->insert('tag',$tag);
				$existing_tag[$tag['tag']] = $this->db->insert_id();
			}
		}

		foreach (array_values($existing_tag) as $tag_id) {
			$this->db->insert('tags2wiki_group', array('wiki_group_id' => $wiki_group_id, 'tag_id' => $tag_id));
			if (array_key_exists($tag_id,$old_tags)) {
				unset($old_tags[$tag_id]);
			}
		}

		
		if (count($old_tags) > 0) {
			//Clean up unused tags within the system
			$sql = "SELECT COUNT(*) as count, tag_id FROM tags2wiki_group WHERE";
			$count = count($old_tags);
			$i=0;
			for ($i=0;$i<$count;$i++) {
				$sql .= " tag_id = ?";
				if ($i!=($count-1)) {
					$sql .= " OR";
				}
			}
			$sql .= " GROUP BY tag_id";
			$query = $this->db->query($sql, array_keys($old_tags));
			foreach ($query->result_array() as $row) {
				if ($row['count'] > 0) {
					unset($old_tags[$row['tag_id']]);
				}
			}
			foreach (array_keys($old_tags) as $old_tag) {
				$this->db->where(array('tag_id' => $old_tag));
				$this->db->delete('tag');
			}
		}
		return $this->get_tags_by_wiki_word($wiki_word);

	}

	function get_wiki_by_wiki_id($wiki_id) {

		$this->db->select('*')->from('wiki')->where('wiki_id',$wiki_id);
		$query = $this->db->get();
		if ($query->num_rows() > 0) {
			return $query->row_array();
		} else {
			return false;
		}

	}

	function check_valid_wiki_word($wiki_word) {

		$regexp = $this->get_wiki_regexp();
		if (preg_match($regexp,$wiki_word)) {
			return true;
		} else {
			return false;
		}
	}

	function update_config($key,$value) {

		$input = array('config_value' => $value);
		$this->db->where('config_key',$key);
		$this->db->update('config',$input);
		return true;
	}

	function get_current_style() {
		$this->db->select('config_value')->from('config')->where('config_key','WikiStyle');
		$query = $this->db->get();
		$wiki_word = $query->row()->config_value;
		return $this->get_style($wiki_word);
	}

	function get_style($wiki_word) {
		$wiki = $this->get_wiki_by_wiki_word($wiki_word);
		return $wiki['content'];
	}

	function get_wiki_word_by_wiki_id($wiki_id) {
		$this->db->select('wiki_word')->from('wiki_group');
		$this->db->join('wiki2group','wiki2group.wiki_group_id = wiki_group.wiki_group_id');
		$this->db->where('wiki2group.wiki_id',$wiki_id);
		$query = $this->db->get();
		return $query->row()->wiki_word;
	}

	function increment_click($wiki_word) {
		$sql = "UPDATE wiki_group SET clicks = clicks + 1 WHERE wiki_word = ?";
		$this->db->query($sql, array($wiki_word));
	}
		
}

?>
